//
//  AVCaptureViewController.h
//  CaptureDemo
//
//  Created by 苏沫离 on 2018/9/11.
//  Copyright © 2018年 苏沫离. All rights reserved.
//

#import <UIKit/UIKit.h>

/* 适用于 iOS 10.2 以上
 *
 * 使用 AVCapturePhotoOutput 捕获图像
 */

API_AVAILABLE(ios(10.2))

@interface AVCaptureViewController : UIViewController

@end


/*
 
OC之AVCapturePhotoOutput


[AVCapturePhotoOutput](https://developer.apple.com/documentation/avfoundation/avcapturephotooutput?changes=latest_minor&language=objc) 是一个静态照片，动态照片和其他摄影工作流程的拍摄输出。它为静态拍摄流程提供了最新接口；除了静态照片的基本拍摄之外，它还支持RAW格式拍摄，多个图像的包围拍摄，动态照片和宽色域颜色。可以输出各种格式和编解码器的拍摄照片，包括RAW格式DNG文件，HEVC格式HEIF文件和JPEG文件。

要使用```AVCapturePhotoOutput```拍摄照片，需按步骤操作：
* 1、创建```AVCapturePhotoOutput```对象，使用其属性确定支持的拍摄设置并启用某些功能：例如，是否拍摄动态照片。
* 2、创建和配置```AVCapturePhotoSettings```对象以选择特定拍摄的功能和设置：例如，是否启用图像稳定或闪光灯。
* 3、通过将```AVCapturePhotoSettings```对象传递给```-capturePhotoWithSettings:delegate:```方法以及实现```AVCapturePhotoCaptureDelegate```协议的委托对象来拍照。然后，```AVCapturePhotoOutput```在拍摄过程中会调用协议方法。

某些照片拍摄设置（如```flashMode```属性）包含自动行为选项。对于此类设置，```AVCapturePhotoOutput```确定是否在拍摄时使用该功能：在请求拍摄时不知道拍摄完成时是否启用该功能。当```AVCapturePhotoOutput```使用有关已完成或正在进行的拍摄的信息调用```AVCapturePhotoCaptureDelegate```方法时，它还提供```AVCaptureResolvedPhotoSettings```对象，该对象详细说明已为该次拍摄设置了哪些自动功能。```AVCaptureResolvedPhotoSettings```的```uniqueID```与用于请求拍摄的```AVCapturePhotoSettings```对象的```uniqueID```值相匹配。
 
 
启用某些照片功能（拍摄动态照片和高分辨率照片）需要重新配置拍摄渲染管道。要选择这些功能，需要在调用```AVCaptureSession```对象的```-startRunning```方法之前设置```highResolutionCaptureEnabled```，```livePhotoCaptureEnabled```和```livePhotoAutoTrimmingEnabled```属性。在```AVCaptureSession```运行时更改这些属性会中断拍摄渲染管道：动态照片拍摄立即结束，未实现的照片请求中止，视频预览暂时冻结。


使用```AVCapturePhotoOutput```会为```AVCaptureSession```对象添加其他要求：
* ```AVCaptureSession```不支持同时进行动态照片拍摄和电影文件输出。如果```AVCaptureSession```包含```AVCaptureMovieFileOutput```对象，则```livePhotoCaptureSupported```属性将变为NO。作为替代方案，可以使用```AVCaptureVideoDataOutput```类与动态照片拍摄相同的分辨率输出视频数据。
* ```AVCaptureSession```不能同时包含```AVCapturePhotoOutput```对象和```AVCaptureStillImageOutput```对象。

```AVCapturePhotoOutput``` 隐式支持宽色域彩色拍摄。如果```AVCaptureDevice```对象的```activeColorSpace```值为```AVCaptureColorSpace_P3_D65```，则```AVCapturePhotoOutput```将生成具有宽颜色信息的照片，除非```AVCapturePhotoSettings```对象指定不支持宽颜色的输出格式。

 
####1、创建```AVCapturePhotoOutput```

```
//初始化新的照片捕获输出对象
- (instancetype)init;
 
//创建一个新的照片捕获输出对象
+ (instancetype)new;
```
 
####2、拍照
 
 
```
- (void)capturePhotoWithSettings:(AVCapturePhotoSettings *)settings
delegate:(id<AVCapturePhotoCaptureDelegate>)delegate;
```

使用指定的设置拍照：
* 参数 ```settings```：拍照设置，例如输出像素格式和闪光灯模式。此方法复制提供的```AVCapturePhotoSettings```对象，因此将来对该对象的更改不会影响正在进行的拍摄。重复使用```AVCapturePhotoSettings```实例进行多次拍摄是非法的。如果它的```uniqueID```值与任何以前使用的设置对象的值匹配，则调用此方法会引发异常```NSInvalidArgumentException```。
* 参数 ```delegate```： 委托对象，用于接收有关拍摄进度和结果的消息。随着照片从拍摄到处理再到完成图像的传递，```AVCapturePhotoOutput```会调用委托方法。

此方法用于静态摄影的所有变体，包括单张拍摄，RAW格式拍摄、JPEG格式拍摄，多个图像的包围拍摄和动态照片拍摄。
 
调用此方法时，```AVCapturePhotoOutput```将验证设置对象的属性以确保确定行为。例如，flashMode设置必须指定```AVCapturePhotoOutput```的```supportedFlashModes```数组中存在的值。[详情可查看AVCapturePhotoSettings](https://www.jianshu.com/p/ed2941276670)
 
 
####3、选择数据和文件格式
 
#####3.1、获取支持的文件类型

> 发送拍照请求时，可以单独指定拍照或编码图像数据的格式以及用于生成包含该数据的输出文件的容器格式。但是，每种文件类型仅支持一组特定的图像数据类型。

属性(```NSArray<AVFileType>```)|描述
-|-
```availablePhotoFileTypes```|```AVCapturePhotoOutput```拍照时支持的文件类型列表。选择文件类型后，调用```-supportedPhotoCodecTypesForFileType:```方法用于以压缩格式如HEVC和JPEG拍摄 或调用```-supportedPhotoPixelFormatTypesForFileType:```方法用于以非压缩格式如TIFF拍摄，在创建```AVCapturePhotoSettings```之前选择适当的数据格式。
```availableRawPhotoFileTypes```|拍摄RAW照片时支持的文件类型列表。选择文件类型后，调用```-supportedRawPhotoPixelFormatTypesForFileType:```方法在创建```AVCapturePhotoSettings```之前选择适当的数据格式。

 
#####3.2、获取支持的像素格式类型

>  仅在将```AVCapturePhotoOutput```添加到包含视频源的```AVCaptureSession```对象后才能读取此属性。如果```AVCapturePhotoOutput```未连接到具有视频源的会话，则格式类型列表为nil。


只读属性|数据类型|描述
-|-|-
```availablePhotoPixelFormatTypes```|```NSArray<NSNumber *>```|```AVCapturePhotoOutput```拍照时支持的像素格式列表。要拍摄未压缩格式照片，例如420f，420v或BGRA，使用```+ photoSettingsWithFormat:```创建```AVCapturePhotoSettings```。在该初始化程序的格式字典中，传递密钥```kCVPixelBufferPixelFormatTypeKey```，其值必须是此数组中列出的像素格式标识符之一。
```availablePhotoCodecTypes```|```NSArray<AVVideoCodecType *>```|拍照时支持的压缩编解码器列表。要拍摄压缩格式如JPEG照片，使用```+ photoSettingsWithFormat:```创建```AVCapturePhotoSettings```。在该初始化程序的格式字典中，传递密钥```AVVideoCodecKey```，其值必须是此数组中列出的编解码器标识符之一。
```availableRawPhotoPixelFormatTypes```|```NSArray<NSNumber *>```|拍摄RAW照片时支持的像素格式列表。非所有设备都支持拍摄RAW图像，如果当前设备不支持拍摄RAW格式，则此列表为nil。要拍摄RAW格式照片，使用```+photoSettingsWithRawPixelFormatType:```或```+photoSettingsWithRawPixelFormatType:processedFormat:```来创建```AVCapturePhotoSettings```。该初始化程序的```rawPixelFormatType```参数的值必须是此数组中列出的Bayer RAW格式标识符之一。


 
#####3.3、指定文件类型后获取支持的像素格式类型

发送拍照请求时，可以单独指定拍照或编码图像数据的格式以及用于生成包含该数据的输出文件的容器格式。但是，每种文件类型仅支持一组特定的图像数据类型。

######3.3.1、指定文件类型后获取支持的未压缩像素格式列表

```
- (NSArray<NSNumber *> *)supportedPhotoPixelFormatTypesForFileType:(AVFileType)fileType;
```

从```availablePhotoFileTypes```数组中选择文件类型后，需要在创建```AVCapturePhotoSettings```之前使用此方法查找兼容的图像数据格式。
* 参数```fileType```：要获取格式信息的文件类型。
* 返回值：支持在指定文件类型中进行编码的像素格式类型数组。

 
######3.3.2、指定文件类型后获取支持的照片编解码器列表


```
- (NSArray<AVVideoCodecType> *)supportedPhotoCodecTypesForFileType:(AVFileType)fileType;
```

从```availablePhotoFileTypes```数组中选择文件类型后，需要在创建```AVCapturePhotoSettings```之前使用此方法查找兼容的图像数据编解码器。
* 参数```fileType```：要获取编解码器信息的文件类型，例如JFIF或HEIF。
* 返回值：支持在指定文件类型中进行编码的视频编解码器类型数组，如JPEG或HEVC。

######3.3.3、指定文件类型后获取支持的的Bayer RAW像素格式列表
 
 
```
- (NSArray<NSNumber *> *)supportedRawPhotoPixelFormatTypesForFileType:(AVFileType)fileType;
```

从```availableRawPhotoFileTypes```数组中选择文件类型后，需要在创建```AVCapturePhotoSettings```之前使用此方法查找兼容的图像数据格式。
* 参数```fileType```：要获取格式信息的文件类型。
* 返回值：支持在指定文件类型中进行编码的像素格式类型数组。



####4、确定可用设置

如果当前```AVCaptureSession```的```sessionPreset```属性或```AVCaptureDevice```的```activeFormat```属性发生更改，则以下属性的值可能会更改。

只读属性|数据类型|描述
-|-|-
```stillImageStabilizationSupported```|```BOOL```|当前拍摄静态图像是否支持自动稳定。要使用图像稳定功能拍照，需要设置```AVCapturePhotoSettings```的```autoStillImageStabilizationEnabled```属性。自动稳定始终包括数字图像稳定，并且还可以包括基于当前设备的光学镜头稳定。如果设备不支持静态图像稳定，则设置```autoStillImageStabilizationEnabled```属性无效，即```AVCaptureResolvedPhotoSettings```的```stillImageStabilizationEnabled```将始终为NO。
```dualCameraFusionSupported```|```BOOL```|当前拍摄是否支持在双摄像头设备上自动组合图像数据；在配备双摄像头的设备上，将两个摄像头的图像融合在一起，以产生更高质量的图像。要使用图像融合拍摄照片，需要设置```AVCapturePhotoSettings```的```autoDualCameraFusionEnabled```属性。如果设备不支持图像融合，则设置```autoDualCameraFusionEnabled```属性不起作用，即```AVCaptureResolvedPhotoSettings```的```dualCameraFusionEnabled```将始终为NO。
```maxBracketedCapturePhotoCount```|```NSUInteger```|拍摄照片可以在单个包围捕获中支持的最大图像数；并非所有设备和拍摄格式都支持包围拍摄。如果当前设备或活动格式不支持括号拍摄，则此属性的值为零。要使用不同的拍摄设置对多个图像进行括号拍摄，需要创建一个```AVCapturePhotoBracketSettings```实例，其中包含所需的设置和括号变体的组合。每次拍摄的最大照片数取决于要拍摄的图像的大小和格式。
```lensStabilizationDuringBracketedCaptureSupported```|```BOOL```|当前在括号内拍照期间是否支持镜头稳定。要在括号内拍摄的整个持续时间内使用光学图像稳定，需要设置```AVCapturePhotoBracketSettings```的```lensStabilizationEnabled```属性。
```supportedFlashModes```|```NSArray<NSNumber *>```|当前支持的闪光灯设置。要设置闪光灯模式，需要将```AVCapturePhotoSettings```的```flashMode```属性设置为此列表值之一。

 
####5、监视可见场景

#####5.1、建议是否使用闪光灯

建议相机当前正在预览的场景是否使用闪光灯，该值会根据镜头可见的场景而变化：例如，iPhone自带相机中的闪光控件，向用户指示场景足够暗，可能需要启用闪光灯。

```
@property(nonatomic, readonly) BOOL isFlashScene;
```

如果```AVCapturePhotoOutput```的```supportedFlashModes```值为```AVCaptureFlashModeOff```，则此属性的值始终为NO。

 
#####5.2、建议是否使用图像稳定
 
建议相机预览的场景是否使用图像稳定，该值会根据镜头可见的场景而变化：例如，iPhone自带相机中与图像稳定相关的控件，向用户指示场景足够暗，可能需要启用图像稳定功能。

```
@property(nonatomic, readonly) BOOL isStillImageStabilizationScene;
```

如果```AVCapturePhotoOutput```的```stillImageStabilizationSupported```值为NO，则此属性的值始终为NO。

 
#####5.3、设置对象

 
用于控制照片输出检测，处理自动闪光模式和稳定模式的照片设置对象。

```
@property(nonatomic, copy) AVCapturePhotoSettings *photoSettingsForSceneMonitoring;
```

设置此对象的```flashMode```和```autoStillImageStabilizationEnabled```属性会影响```AVCapturePhotoOutput```的场景监视属性```isFlashScene```和```isStillImageStabilizationScene```的值。例如，如果将此对象的```flashMode```属性设置为```AVCaptureFlashModeOff```，则无论可见场景中的光照条件如何，照片输出的```isFlashScene```属性都会为NO。如果将此照片设置对象的```flashMode```属性设置为```AVCaptureFlashModeAuto```或```AVCaptureFlashModeOn```，则```AVCapturePhotoOutput```的```isFlashScene```属性将恢复为基于可见光级别返回YES或NO的默认行为。



 > 注意：在亮度范围有一些重叠，这得益于静态图像稳定和闪光。如果此对象指示应监视静止图像稳定和闪光的场景，则静止图像稳定优先，并且```isFlashScene```属性在较低的整体亮度下变为YES。
 
 
 默认值为```AVCapturePhotoSettings```对象，具有以下设置：
 * ```flashMode```：取值```AVCaptureFlashModeAuto```
 * ```autoStillImageStabilizationEnabled```：取值YES
 
```AVCapturePhotoOutput```会忽略此对象的所有其他属性。要在请求拍摄时控制其他照片设置，需要创建```AVCapturePhotoSettings```以传递给```-capturePhotoWithSettings:delegate:```方法。
 
 
####6、配置高分辨率静态拍摄

一个布尔值，指定是否为拍摄高分辨率静态图像配置捕获管道。

```
@property(nonatomic, getter=isHighResolutionCaptureEnabled) BOOL highResolutionCaptureEnabled;
```

某些拍摄格式支持静态图像的输出，其分辨率高于用于实时预览和视频捕获的分辨率。在某些情况下，```AVCaptureSession```需要以不同方式设置其内部渲染管道，以支持高分辨率静态图像捕获。

如果打算采用高分辨率静止图像，需要在调用```AVCaptureSession```的 ```-startRunning```方法之前设置此属性。在```AVCaptureSession```运行时更改此属性需要对捕获渲染管道进行冗长的重新配置：正在进行的动态照片拍摄将立即结束，未实现的照片请求将中止，视频预览将暂时冻结。

在请求拍照之前，必须启用此选项，并将```AVCapturePhotoSettings```的```highResolutionPhotoEnabled```属性设置为YES。但是，启用此选项后，可以使用任何```highResolutionPhotoEnabled```设置自由发出拍照请求。

 
####7、拍摄动态照片配置
 
 一个布尔值，指示捕获输出当前是否支持实时照片捕获。
 @property(nonatomic, readonly, getter=isLivePhotoCaptureSupported) BOOL livePhotoCaptureSupported;

 实时照片捕获以拍摄时刻为中心的静止图像和短片，它们在用户界面（如照片应用程序）中一起显示。
 
 并非所有设备和捕获格式都支持实时照片捕获。 如果当前捕获会话的sessionPreset属性或基础捕获设备的activeFormat属性发生更改，则此属性的值可能会更改。 如果相机或格式更改导致此属性的值变为NO，则livePhotoCaptureEnabled属性的值也将变为NO。
 
 
 
 一个布尔值，指定是否为Live Photo捕获配置捕获管道。
 @property(nonatomic, getter=isLivePhotoCaptureEnabled) BOOL livePhotoCaptureEnabled;
 实时照片捕获以拍摄时刻为中心的静止图像和短片，它们在用户界面（如照片应用程序）中一起显示。
 
 捕获实时照片要求捕获会话以不同方式设置其内部渲染管道。 如果您打算完全拍摄Live Photos，请在调用AVCaptureSession startRunning方法之前将此属性设置为YES。 在会话运行时更改此属性需要对捕获渲染管道进行冗长的重新配置：正在进行的实时照片捕获将立即结束，未实现的照片请求将中止，视频预览将暂时冻结。
 
 在使用设置为非零的照片设置对象的livePhotoMovieFileURL属性启动照片捕获之前，必须启用此选项。 但是，启用此选项后，您可以自由发布实时照片和静态照片的照片捕获请求。
 
 
 
 一个布尔值，指定是否暂停但不禁用Live Photo捕获。
 @property(nonatomic, getter=isLivePhotoCaptureSuspended) BOOL livePhotoCaptureSuspended;

 使用此属性可以缩短当前正在进行的实时照片动画捕捉 - 例如，如果您突然需要执行一些您不希望在动态照片电影中显示的内容，例如拍摄快照的静态照片 声音。
 
 默认情况下，此属性的值为NO。 当您将值更改为YES时，正在进行的任何实时照片捕获将被剪裁到当前时间。 同样，当您将此属性的值从YES更改为NO时，后续的Live Photo影片捕获将不包含任何早于取消暂停Live Photo捕获的样本的样本。
 
 如果livePhotoCaptureEnabled属性的值为NO，则将此属性设置为YES会引发异常（NSInvalidArgumentException）。
 
 
 

 
 一个布尔值，指定是否自动修剪Live Photo影片捕获以避免过度移动。
 @property(nonatomic, getter=isLivePhotoAutoTrimmingEnabled) BOOL livePhotoAutoTrimmingEnabled;

 使用此选项可启用“相机”应用中的相同自动修剪行为。 默认情况下，实时照片捕获持续时间约为三秒（以捕获请求的时间为中心）。 但是，如果用户在拍摄期间升高或降低相机，iOS会实时分析电影捕捉并自动修剪实时照片的持续时间，以避免捕获过多的移动。
 
 当livePhotoCaptureSupported为YES时，此属性的值也默认为YES。
 
 启用或禁用此功能要求捕获会话以不同方式设置其内部呈现管道。 为获得最佳结果，请在调用AVCaptureSession startRunning方法之前更改此属性的值。 在会话运行时更改此属性需要对捕获渲染管道进行冗长的重新配置：正在进行的实时照片捕获将立即结束，未实现的照片请求将中止，视频预览将暂时冻结。
 
 
 当前可用于使用照片输出捕获实时照片的视频编解码器列表。
 @property(nonatomic, readonly) NSArray<AVVideoCodecType> *availableLivePhotoVideoCodecTypes;
 默认情况下，Live Photo捕获使用H.264编解码器对Live Photo的电影部分进行编码。 要使用其他编解码器，请将照片设置对象的livePhotoVideoCodecType属性设置为此数组中的某个值。
 
 对数组进行排序，以便首先列出系统的默认（首选）视频编解码器。 如果您尚未将照片输出添加到带有视频源的AVCaptureSession，则无法使用任何编解码器。
 
 
 
 
 
 8、配置深度数据捕获
 
 
 一个布尔值，指示捕获输出当前是否支持深度数据捕获。
 @property(nonatomic, readonly, getter=isDepthDataDeliverySupported) BOOL depthDataDeliverySupported;
 深度数据捕获与照片图像一起传送的场景深度信息的每像素图，并且可选地嵌入图像文件输出中。 深度数据可用于诸如应用深度敏感的照片滤镜效果（如iOS相机应用程序的肖像模式中所见）和执行计算机视觉任务等目的。
 
 并非所有设备和捕获格式都支持深度捕获。 如果当前捕获会话的sessionPreset属性或基础捕获设备的activeFormat属性发生更改，则此属性的值可能会更改。 如果摄像头或格式更改导致此属性的值变为NO，则depthDataDeliveryEnabled属性的值也将变为NO。
 
 
 
 一个布尔值，指定是否配置捕获管道以进行深度数据捕获。
 @property(nonatomic, getter=isDepthDataDeliveryEnabled) BOOL depthDataDeliveryEnabled;
 深度数据捕获与照片图像一起传送的场景深度信息的每像素图，并且可选地嵌入图像文件输出中。深度数据可用于诸如应用深度敏感的照片滤镜效果（如iOS相机应用程序的肖像模式中所见）和执行计算机视觉任务等目的。
 
 捕获深度数据要求捕获会话以不同方式设置其内部渲染管道。如果您打算捕获深度数据，请在调用AVCaptureSession startRunning方法之前将此属性设置为YES。在会话运行时更改此属性需要对捕获渲染管道进行冗长的重新配置：正在进行的实时照片捕获将立即结束，未实现的照片请求将中止，视频预览将暂时冻结。
 
 在启动照片捕获之前，必须启用此选项，并将照片设置对象的depthDataDeliveryEnabled属性设置为YES。但是，启用此选项后，您可以使用和不使用深度数据发出照片捕获请求。
 
 
 
 
 9、配置纵向效果遮罩捕捉
 
 一个布尔值，指示捕获输出是否将生成纵向效果遮罩。
 @property(nonatomic, getter=isPortraitEffectsMatteDeliveryEnabled) BOOL portraitEffectsMatteDeliveryEnabled;

 一个布尔值，指示捕获输出当前是否支持传送纵向效果遮罩。
 @property(nonatomic, readonly, getter=isPortraitEffectsMatteDeliverySupported) BOOL portraitEffectsMatteDeliverySupported;

 
 
 
 10、配置双摄像头捕获
 
 
 一个布尔值，指示捕获输出当前是否支持在双摄像头设备上同时使用两个摄像头进行照片捕获。
 @property(nonatomic, readonly, getter=isDualCameraDualPhotoDeliverySupported) BOOL dualCameraDualPhotoDeliverySupported;
并非所有设备和捕获格式都支持双摄像头捕获。 如果当前捕获会话的sessionPreset属性或基础捕获设备的activeFormat属性发生更改，则此属性的值可能会更改。 如果相机或格式更改导致此属性的值变为NO，则dualCameraDualPhotoDeliveryEnabled属性的值也将变为NO。
 
 
 
 一个布尔值，指示捕获输出当前是否支持传送摄像机校准数据。
 @property(nonatomic, readonly, getter=isCameraCalibrationDataDeliverySupported) BOOL cameraCalibrationDataDeliverySupported;
AVCameraCalibrationData对象描述了设备摄像头的成像参数，对于在双摄像头设备上与双照片传送一起执行计算机视觉任务非常有用。仅当dualCameraDualPhotoDeliveryEnabled属性为YES时，此属性的值才为YES。 要启用摄像机校准传送，请在照片设置对象中设置cameraCalibrationDataDeliveryEnabled属性。
 
 
 
 
 一个布尔值，指定是否配置捕获管道，以便在双摄像头设备上同时使用两个摄像头进行照片捕获。
 @property(nonatomic, getter=isDualCameraDualPhotoDeliveryEnabled) BOOL dualCameraDualPhotoDeliveryEnabled;
 启用此属性（在支持的设备上）允许捕获输出在单次捕获中从广角和长焦相机提供单独的图像。
 
 双照片传送要求捕获会话以不同方式设置其内部渲染管道。 如果您打算使用双照片传送捕获，请在调用AVCaptureSession startRunning方法之前将此属性设置为YES。 在会话运行时更改此属性需要对捕获渲染管道进行冗长的重新配置：正在进行的实时照片捕获将立即结束，未实现的照片请求将中止，视频预览将暂时冻结。
 
 在使用照片设置对象的dualCameraDualPhotoDeliveryEnabled属性设置为YES启动照片捕获之前，必须启用此选项。 但是，启用此选项后，您可以在有和没有双照片传送的情况下发出照片捕获请求。
 
 
 
 
 
 
 
 
 
 11、准备资源密集的捕获   Preparing for Resource-Intensive Captures

 
 
 照片输出已准备好的一系列照片设置捕获资源。
 @property(nonatomic, readonly) NSArray<AVCapturePhotoSettings *> *preparedPhotoSettingsArray;
 某些类型的照片捕获（例如括号内捕获和RAW捕获）需要照片输出来分配额外的缓冲区或准备其他资源。 为了防止照片捕获请求由于延迟资源分配而缓慢执行，您可以使用一组设置对象调用setPreparedPhotoSettingsArray：completionHandler：方法，该对象代表您将要执行的捕获类型（例如括号捕获的设置，RAW捕获 ，或使用静止图像稳定捕获）。
 
 默认情况下，照片输出准备足够的资源以使用默认设置捕获照片（由AVCapturePhotoSettings默认初始化程序定义）。
 
 
 
 告知照片捕获输出，以便为将来使用指定设置的捕获请求准备资源。
 - (void)setPreparedPhotoSettingsArray:(NSArray<AVCapturePhotoSettings *> *)preparedPhotoSettingsArray
 completionHandler:(void (^)(BOOL prepared, NSError *error))completionHandler;
 参数：preparedPhotoSettingsArray 一组照片捕获设置对象，指示照片输出应为其准备资源的捕获类型。
 参数：completionHandler 在照片输出完成准备资源后，在串行调度队列上调用的完成块。 如果您不希望在准备工作完成时收到通知，则通过nil。
 
 
 某些类型的照片捕获（例如括号内捕获和RAW捕获）需要照片输出来分配额外的缓冲区或准备其他资源。为了防止由于资源分配延迟导致照片捕获请求执行缓慢，您可以使用一组设置对象来调用此方法，这些对象代表您将要执行的捕获类型（例如括号捕获，RAW捕获或捕获的设置）静止图像稳定）。
 
 默认情况下，照片输出准备足够的资源以使用默认设置捕获照片（由AVCapturePhotoSettings默认初始化程序定义）。要回收所有可能的资源，请使用空数组调用此方法。
 
 每次使用一组设置调用此方法时，照片输出将评估需要分配的其他资源以及可回收的现有资源，并在完成准备（并可能需要回收）时调用completionHandler块资源。要提供有关您打算使用哪些捕获功能的早期提示，您甚至可以在捕获会话上调用startRunning方法之前调用此方法。
 
 照片捕获的准备始终是可选的。您可以在不首先调用此方法的情况下调用capturePhotoWithSettings：delegate：方法 - 但是，由于捕获系统会在即时基础上分配其他资源，因此您的某些照片捕获可能会执行得很慢。
 
 
 如果在捕获会话未运行时调用此方法，则不会立即调用completionHandler块。只有在捕获会话上调用startRunning方法并且实际已准备好所需资源后，照片输出才会调用完成处理程序。如果使用一组设置调用setPreparedPhotoSettingsArray：completionHandler：方法，然后再次调用它，则第一个调用的完成处理程序将立即触发，并准备好参数NO。
 
 准备好的设置会在会话启动/停止和已提交的配置更改之间保持不变，并参与AVCaptureSession类定义的延迟工作行为。也就是说，如果您调用捕获会话的beginConfiguration方法，更改会话的输入/输出拓扑，然后调用此方法，捕获会话将推迟任何准备工作，直到您调用commitConfiguration方法。此模式允许您以原子方式提交新配置，并准备在新配置中拍摄照片。
 
 调用此方法并触发completionHandler块后，preparedPhotoSettingsArray属性将列出捕获系统已为其准备资源的照片设置。
 
 
 
 
 12、获取格式化输出数据 iOS10.0 ~ iOS11.0
 
 
 在iOS 11及更高版本中，在捕获委托中实现captureOutput：didFinishProcessingPhoto：error：方法，并使用生成的AVCapturePhoto对象的fileDataRepresentation方法。
 
 
 返回与指定样本缓冲区中捕获的照片对应的JPEG格式的数据。
 + (NSData *)JPEGPhotoDataRepresentationForJPEGSampleBuffer:(CMSampleBufferRef)JPEGSampleBuffer
 previewPhotoSampleBuffer:(CMSampleBufferRef)previewPhotoSampleBuffer;
 参数：JPEGSampleBuffer    包含JPEG照片捕获结果的样本缓冲区，用于格式化输出。
 参数：previewPhotoSampleBuffer    包含照片捕获结果的预览分辨率版本的可选附加样本缓冲区，将作为缩略图添加到JPEG输出中。 传递零以跳过将预览图像添加到输出。
 返回值：包含所请求的照片捕获结果的JPEG表示的数据对象，如果无法打包样本缓冲区以进行输出，则为nil。
 
 使用capturePhotoWithSettings：delegate：方法请求照片捕获后，照片捕获输出将结果作为一个或多个CMSampleBufferRef对象传递给您的委托。 （请参阅captureOutput：didFinishProcessingPhotoSampleBuffer：previewPhotoSampleBuffer：resolvedSettings：bracketSettings：error：method。）要重新打包样本缓冲区的内容以作为JPEG文件输出，请使用此类方法。 （可选）通过在调用此方法之前将元数据附加到样本缓冲区，可以在生成的JPEG输出中包含元数据。
 
 jpegSampleBuffer参数必须从JPEG捕获引用样本缓冲区。 请参阅照片捕获设置的format属性。
 
 
 
 
 
 
 
 返回与指定样本缓冲区中捕获的RAW照片对应的数字负片（DNG）格式的数据。
 + (NSData *)DNGPhotoDataRepresentationForRawSampleBuffer:(CMSampleBufferRef)rawSampleBuffer
 previewPhotoSampleBuffer:(CMSampleBufferRef)previewPhotoSampleBuffer;
 参数：rawSampleBuffer 包含RAW照片捕获结果的样本缓冲区，用于格式化输出。
 参数：previewPhotoSampleBuffer 包含照片捕获结果的预览分辨率版本的可选附加样本缓冲区，将作为缩略图添加到DNG输出中。 传递零以跳过将预览图像添加到输出。
 返回值：包含所请求的照片捕获结果的DNG表示的数据对象，如果无法打包样本缓冲区以进行输出，则为nil。
 
 使用capturePhotoWithSettings：delegate：方法请求照片捕获后，照片捕获输出将结果作为一个或多个CMSampleBufferRef对象传递给您的委托。 （请参阅captureOutput：didFinishProcessingRawPhotoSampleBuffer：previewPhotoSampleBuffer：resolvedSettings：bracketSettings：error：method。）要重新打包样本缓冲区的内容以作为DNG文件输出，请使用此类方法。 （可选）您可以在调用此方法之前将元数据附加到样本缓冲区中，从而在生成的DNG输出中包含元数据。
 
 rawSampleBuffer参数必须从RAW捕获引用样本缓冲区。 请参阅rawPhotoPixelFormatType属性以获取照片捕获设置。
 
 
 
 */
